/*******************************************************************************
 * CBPage.m
 * ComicsBlog
 *
 * Adrien Bougouin <adrien.bougouin@gmail.com>
 */

#import "CBPage.h"

@implementation CBPage

@synthesize _lastErrorMessage;

- (id) initWithCategory:(NSUInteger) category {
  self = [super init];

  if(self) {
    _scriptURL = [[NSString alloc] initWithFormat:@"%@?format=xml&cat=%lu",
                                                  CBPageScriptURL,
                                                  (unsigned long) category];
    _lastErrorMessage = @"";
    _news             = [[NSMutableArray alloc] init];
    _scriptConnection = nil;
    _xmlParser        = nil;
    _tempDatas        = nil;
    _tempIdentifier   = 0;
    _tempTitle =       nil;
    _tempPubDate      = nil;
    _tempHDImage      = nil;
    _tempImage        = nil;
    _tempFile         = nil;
    _tempDescription  = nil;
    _tempCategory     = 0;
    _tempType         = nil;
    _parsingState     = NOP;
  }

  return self;
}

- (void) dealloc {
  [super dealloc];

  [_scriptConnection cancel];
  [_xmlParser abortParsing];

  [_scriptURL         release];
  [_news              release];
  [_scriptConnection  release];
  [_xmlParser         release];
  [_tempDatas         release];
  [_tempHDImage       release];
  [_tempImage         release];
  [_tempFile          release];
  [_tempTitle         release];
  [_tempPubDate       release];
  [_tempDescription   release];
  [_tempType          release];
}

- (void) loadNewsFrom:(NSUInteger) from length:(NSUInteger) length {
  NSString *requestString = [NSString stringWithFormat:@"%@&start=%lu&length=%lu",
                                                       _scriptURL,
                                                       (unsigned long) from,
                                                       (unsigned long) length];
  NSURL *scriptURL = [[NSURL alloc] initWithString:requestString];
  NSURLRequest *scriptRequest = [[NSURLRequest alloc] initWithURL:scriptURL];

  [_scriptConnection release];
  [_xmlParser release];

  _scriptConnection = [[NSURLConnection alloc] initWithRequest:scriptRequest
                                                      delegate:self];
  _xmlParser = nil;

  [_scriptConnection start];

  // memory management
  [scriptURL      release];
  [scriptRequest  release];
}

- (void) notifyWithName:(NSString *) name {
  // add a new autorelease pool to the stack
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  NSNotification *notification = [NSNotification notificationWithName:name
                                                               object:self];
  NSUInteger coalesceMask = NSNotificationCoalescingOnName
                            | NSNotificationCoalescingOnSender;

  [[NSNotificationQueue defaultQueue] enqueueNotification:notification
                                             postingStyle:NSPostASAP
                                             coalesceMask:coalesceMask
                                                 forModes:nil];

  // delete the local autorelease pool then dealloc autoreleased objects used by
  // the method
  [pool release];
}

- (void) notifyUpdated {
  [self notifyWithName:CBPageUpdatedNotificationName];
}

- (void) notifyError {
  [self notifyWithName:CBPageErrorNotificationName];
}

- (NSUInteger) numberOfNews {
  NSInteger count = [_news count];

  return count;
}

- (CBNews *) newsAtIndex:(NSUInteger) index {
  return [_news objectAtIndex:index];
}

//==============================================================================
// NSURLConnectionDelegate
//==============================================================================

- (void) connection:(NSURLConnection *) connection
     didReceiveData:(NSData *) data {
  //update the temporary datas
  if(!_tempDatas) {
    _tempDatas = [[NSMutableData alloc] init];

    [_tempDatas setData:data];
  } else {
    [_tempDatas appendData:data];
  }
}

- (void) connection:(NSURLConnection *) connection
   didFailWithError:(NSError *) error {
  [self notifyError];
  _lastErrorMessage = @"Vérifiez votre connexion Internet !";

  // memory management
  [_tempDatas release];
  _tempDatas = nil;
}

- (void) connectionDidFinishLoading:(NSURLConnection *) connection {
  if(_tempDatas) {
    _xmlParser = [[NSXMLParser alloc] initWithData:_tempDatas];

    [_xmlParser setDelegate:self];
    [_xmlParser parse];

    // memory management
    [_tempDatas release];
    _tempDatas = nil;
  }
}

//==============================================================================
// NSXMLParserDelegate
//==============================================================================

- (void) parserDidStartDocument:(NSXMLParser *) parser {
  _parsingState = NOP;
}

- (void) parser:(NSXMLParser *) parser parseErrorOccured:(NSError *) error {
  [self notifyError];
  _lastErrorMessage = @"Erreur de traitement des données !";
}

- (void) parserDidEndDocument:(NSXMLParser *) parser {
  [self notifyUpdated];
}

- (void)   parser:(NSXMLParser *) parser
  didStartElement:(NSString *) elementName
     namespaceURI:(NSString *) namespaceURI
    qualifiedName:(NSString *) qualifiedName
       attributes:(NSDictionary *) attributeDict {
  if([elementName isEqual:@"entry"]) {
    [_tempTitle       release];
    [_tempHDImage     release];
    [_tempImage       release];
    [_tempFile        release];
    [_tempPubDate     release];
    [_tempDescription release];
    [_tempType        release];
    _tempIdentifier   = 0;
    _tempTitle        = nil;
    _tempHDImage      = nil;
    _tempImage        = nil;
    _tempFile         = nil;
    _tempPubDate      = nil;
    _tempDescription  = nil;
    _tempCategory     = 0;
    _tempType         = nil;
    _parsingState = NOP;
  } else if([elementName isEqual:@"id_n"]) {
    _parsingState = ID;
  } else if([elementName isEqual:@"date"]) {
    _parsingState = DATE;
  } else if([elementName isEqual:@"titre_fr"]) {
    _parsingState = TITLE;
  } else if([elementName isEqual:@"image"]) {
    _parsingState = IMAGE;
  } else if([elementName isEqual:@"fichier"]) {
    _parsingState = FFILE;
  } else if([elementName isEqual:@"description_fr"]) {
    _parsingState = DESCRIPTION;
  } else if([elementName isEqual:@"cat"]) {
    _parsingState = CATEGORY;
  } else if([elementName isEqual:@"type"]) {
    _parsingState = TYPE;
  } else {
    _parsingState = NOP;
  }
}

- (void) parser:(NSXMLParser *) parser
  didEndElement:(NSString *) elementName
   namespaceURI:(NSString *) namespaceURI
  qualifiedName:(NSString *) qualifiedName {
  // add a new autorelease pool to the stack
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  if([elementName isEqual:@"entry"]) {
    NSCharacterSet *trimSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
    NSString *trimmedHDImageURL = [_tempHDImage stringByTrimmingCharactersInSet:trimSet];
    NSRange hdImageRange = NSMakeRange(0, [trimmedHDImageURL length]);
    NSString *hdImageURL = [trimmedHDImageURL stringByReplacingOccurrencesOfString:@" "
                                                                        withString:@"\%20"
                                                                           options:0
                                                                             range:hdImageRange];
    NSString *trimmedImageURL = [_tempImage stringByTrimmingCharactersInSet:trimSet];
    NSRange imageRange = NSMakeRange(0, [trimmedImageURL length]);
    NSString *imageURL = [trimmedImageURL stringByReplacingOccurrencesOfString:@" "
                                                                    withString:@"\%20"
                                                                       options:0
                                                                         range:imageRange];
    NSString *trimmedFileURL = [_tempFile stringByTrimmingCharactersInSet:trimSet];
    NSRange fileRange = NSMakeRange(0, [trimmedFileURL length]);
    NSString *fileURL = [trimmedFileURL stringByReplacingOccurrencesOfString:@" "
                                                                  withString:@"\%20"
                                                                     options:0
                                                                       range:fileRange];
    CBNews *news = [[CBNews alloc] initWithID:_tempIdentifier
                                        title:[_tempTitle stringByTrimmingCharactersInSet:trimSet]
                                       author:@"COMICSBLOG"
                                      pubDate:[_tempPubDate stringByTrimmingCharactersInSet:trimSet]
                                      hdImage:hdImageURL
                                        image:imageURL
                                         file:fileURL
                                  description:[_tempDescription stringByTrimmingCharactersInSet:trimSet]
                                     category:_tempCategory
                                         type:[_tempType stringByTrimmingCharactersInSet:trimSet]];

    [_news addObject:news];

    // memory management
    [news               release];
    [_tempTitle         release];
    [_tempPubDate       release];
    [_tempHDImage       release];
    [_tempImage         release];
    [_tempFile          release];
    [_tempDescription   release];
    [_tempType          release];
    _tempTitle        = nil;
    _tempPubDate      = nil;
    _tempHDImage      = nil;
    _tempImage        = nil;
    _tempFile         = nil;
    _tempDescription  = nil;
    _tempType         = nil;
  }

  // delete the local autorelease pool then dealloc autoreleased objects used by
  // the method
  [pool release];
}

- (void) parser:(NSXMLParser *) parser foundCharacters:(NSString *) string {
  switch(_parsingState) {
    case ID:
      _tempIdentifier = [string integerValue];
    break;

    case DATE:
      if(_tempPubDate == nil) {
        _tempPubDate = [[NSMutableString alloc] init];
      }

      [_tempPubDate appendString:string];
    break;

    case TITLE:
      if(_tempTitle == nil) {
        _tempTitle = [[NSMutableString alloc] init];
      }

      [_tempTitle appendString:string];
    break;

    case IMAGE:
      if(_tempHDImage == nil) {
        _tempHDImage = [[NSMutableString alloc] initWithString:CBPageHDImageURL];
      }
      if(_tempImage == nil) {
        _tempImage = [[NSMutableString alloc] initWithString:CBPageImageURL];
      }

      [_tempHDImage appendString:string];
      [_tempImage appendString:string];
    break;

    case FFILE:
      if(_tempFile == nil) {
        _tempFile = [[NSMutableString alloc] initWithString:CBPageFileURL];
      }

      [_tempFile appendString:string];
    break;

    case DESCRIPTION:
      if(_tempDescription == nil) {
        _tempDescription = [[NSMutableString alloc] init];
      }

      [_tempDescription appendString:string];
    break;

    case CATEGORY:
      if(_tempCategory == 0) {
        _tempCategory = [string integerValue];
      }
    break;

    case TYPE:
      if(_tempType == nil) {
        _tempType = [[NSMutableString alloc] init];
      }

      [_tempType appendString:string];
    break;
  }
}

@end

